package org.zfes.snowier.cloud.zbss.asf.biz.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;

import com.arcsoft.face.AgeInfo;
import com.arcsoft.face.Face3DAngle;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.FunctionConfiguration;
import com.arcsoft.face.GenderInfo;
import com.arcsoft.face.LivenessInfo;
import com.arcsoft.face.enums.ImageFormat;

import org.zfes.snowier.core.data.DataSet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.zfes.snowier.core.util.ZBeanUtil;
import org.zfes.snowier.core.util.ZStrUtil;

import com.google.common.collect.Maps;

import org.zfes.snowier.core.util.ZAlert;
import org.zfes.snowier.core.util.ZAssert;
import org.zfes.snowier.common.dao.params.ParamMap;
import org.zfes.snowier.common.file.disk.UploadConst;
import org.zfes.snowier.cloud.zbss.asf.biz.service.IFaceEngineService;
import org.zfes.snowier.cloud.zbss.asf.biz.service.IUserFaceInfoService;
import org.zfes.snowier.cloud.zbss.asf.biz.util.ImageUtil;
import org.zfes.snowier.cloud.zbss.asf.biz.cache.IUserDataSet;
import org.zfes.snowier.cloud.zbss.asf.biz.consts.BizConsts;
import org.zfes.snowier.cloud.zbss.asf.biz.dao.UserFaceInfoMapper;
import org.zfes.snowier.cloud.zbss.asf.biz.dto.ImageInfo;
import org.zfes.snowier.cloud.zbss.asf.biz.dto.ProcessResDto;
import org.zfes.snowier.cloud.zbss.asf.biz.dto.UserFaceInfoCreateDto;
import org.zfes.snowier.cloud.zbss.asf.biz.dto.UserFaceInfoUpdateDto;
import org.zfes.snowier.cloud.zbss.asf.biz.model.UserFaceInfo;
import java.util.stream.Stream;
@Service
public class UserFaceInfoServiceImpl implements IUserFaceInfoService{
	
	public static final long batchSize=500;
	
	
 	@Autowired
	private UserFaceInfoMapper userFaceInfoMapper;
 	@Autowired
	private IFaceEngineService faceEngineService;

 	@Autowired
	private  IUserDataSet  userDataSet;
 	


    
	@Transactional(rollbackFor=Exception.class)
 	@Override
	public UserFaceInfo createUserFaceInfo(UserFaceInfoCreateDto userFaceInfo) {
		ZBeanUtil.setCreateInfo(userFaceInfo);
		ZBeanUtil.validateBean(userFaceInfo);
		
		Object id2=userFaceInfoMapper.selectIdByPhone(userFaceInfo.getPhone());
		if(id2!=null){
			ZAlert.throwSLE("电话已经存在");
		}
		
		Object id3=userFaceInfoMapper.selectIdByEmail(userFaceInfo.getEmail());
		if(id3!=null){
			ZAlert.throwSLE("邮箱已经存在");
		}
		UserFaceInfo user=new UserFaceInfo();
		ZBeanUtil.copy(userFaceInfo, user, true);
		
		 String absolutePath=new StringBuilder()
				 .append(ZStrUtil.substringBeforeLast(new File(".").getAbsolutePath(), "."))
				 .append(File.separator)
				 .append(UploadConst.fileRootPath)
				 .append(File.separator) 
				 .append(userFaceInfo.getFacePic().replaceAll("/", Matcher.quoteReplacement(File.separator))).toString();
		 
		Optional<ImageInfo> imageInfoOp=ImageUtil.getRGBData(new File(absolutePath));
		ZAssert.notEmpty(imageInfoOp, "请先采集图像信息");

		List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfoOp.get());
		ZAssert.notEmpty(faceInfoList,"未检测到人脸");

		
		ProcessResDto processRes=faceEngineService.process(imageInfoOp.get(),faceInfoList);
		user.setAge(processRes.getAge());
		
		user.setGender(processRes.getGender());
		
		byte[] feature= faceEngineService.extractFaceFeature(imageInfoOp.get(),faceInfoList);
		user.setFaceFeature(feature);
		
		userFaceInfoMapper.insertSelective(user);
		
		userDataSet.add(user);
		
		return new UserFaceInfo(user).setFaceFeature(null);
		
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updateUserFeaturePic(Long id, String facePic) {
		
		Optional<ImageInfo> imageInfoOp = ImageUtil.getRGBData(new File(BizConsts.imgRootPath+facePic));
		ZAssert.notEmpty(imageInfoOp, "请先采集图像信息");

		List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfoOp.get());
		ZAssert.notEmpty(faceInfoList,"未检测到人脸");

		
		UserFaceInfo user=new UserFaceInfo(id);
		
		
		ProcessResDto processRes = faceEngineService.process(imageInfoOp.get(),faceInfoList);
		user.setAge(processRes.getAge());
		user.setGender(processRes.getGender());
		
		
		byte[] feature= faceEngineService.extractFaceFeature(imageInfoOp.get(),faceInfoList);
		user.setFaceFeature(feature);
		
		userFaceInfoMapper.updateByPrimaryKeySelective(user);
		
		
		loadUserFaceInfoById( id).ifPresent(val->{
			userDataSet.remove(val);
			userDataSet.add(val);
		});
		
		
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<UserFaceInfo> loadUserFaceInfoById(Long id) {
		if(id!=null){
			return Optional.ofNullable(userFaceInfoMapper.selectByPrimaryKey(id));
		}
		return Optional.empty();
		
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updateUserFaceInfo(UserFaceInfoUpdateDto userFaceInfo) {
		ZBeanUtil.setUpdatedInfo(userFaceInfo);
		ZBeanUtil.validateBean(userFaceInfo);
		ZAssert.notNull(userFaceInfo.getId(), "ID参数错误");
		
		Object id2=userFaceInfoMapper.selectIdByPhone(userFaceInfo.getPhone());
		if(id2!=null&&!id2.equals(userFaceInfo.getId())){
			ZAlert.Error("电话已经存在");
		}
		Object id3=userFaceInfoMapper.selectIdByEmail(userFaceInfo.getEmail());
		if(id3!=null&&!id3.equals(userFaceInfo.getId())){
			ZAlert.Error("邮箱已经存在");
		}
		UserFaceInfo user=new UserFaceInfo();
		ZBeanUtil.copy(userFaceInfo, user, true);
		
		userFaceInfoMapper.updateByPrimaryKeySelective(user);
	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void deleteUserFaceInfo(Long id) {
		ZAssert.notNull(id, "请选择要操作的数据");
		
		loadUserFaceInfoById( id).ifPresent(val->{
			userDataSet.remove(val);
		});
		userFaceInfoMapper.deleteByPrimaryKey(id);
	
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setUserFaceInfoStatus(Long id, Byte status) {
		ZAssert.notNull(id, "请选择要操作的数据");
		ZAssert.notNull(status, "状态参数错误");
		if(!Stream.of(new Byte[] {-1,0,1}).anyMatch(val->val.equals(status))) {
			ZAlert.serviceLogicalError("状态参数错误");
		}
		userFaceInfoMapper.updateStatus( id,  status) ;
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public DataSet loadUserFaceInfoDataSet(Map<String, Object> params) {
		ParamMap pm=ParamMap.filterParam(params);
		DataSet ds=DataSet.newDS2(userFaceInfoMapper.selectListCount(pm), userFaceInfoMapper.selectMapListPage(pm));
		return ds;
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<UserFaceInfo> loadByPhone(java.lang.String phone){
		if(phone!=null){
			return Optional.ofNullable(userFaceInfoMapper.selectByPhone(phone));
		}
		return Optional.empty();
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<UserFaceInfo> loadByEmail(java.lang.String email){
		if(email!=null){
			return Optional.ofNullable(userFaceInfoMapper.selectByEmail(email));
		}
		return Optional.empty();
	}


	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Long initUserdataSet() {
		Long count=userFaceInfoMapper.selectListCount(ParamMap.newNonePm());
		int loopNum=(int) (count%batchSize==0?count/batchSize:count/batchSize+1);
		
		for(int i=1 ; i <= loopNum ; i++ ) {
			Map<String,Object> params =Maps.newHashMap();
			params.put("size", batchSize);
			params.put("page", Long.valueOf(i));
			params.put("order", "asc");
			params.put("sort", "id");
			List<UserFaceInfo>  userList=userFaceInfoMapper.selectModelListPage(ParamMap.filterParam(params));
			userDataSet.addAll(userList);
		}
		return Long.valueOf(userDataSet.size());
	}
	
	
}